/**
 * Copyright (c) Software Institute of PKU
 * All rights reserved. 
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */
package edu.pku.sei.modeler.editparts;

import java.beans.PropertyChangeEvent;
import java.util.Iterator;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.DirectEditPolicy;
import org.eclipse.gef.requests.DirectEditRequest;

import edu.pku.sei.modeler.editpolicies.UMLDiagramGraphicalNodeEditPolicy;
import edu.pku.sei.modeler.figures.UMLClassFigure;
import edu.pku.sei.modeler.model.common.MetaTypedList;
import edu.pku.sei.modeler.model.structure.MetaNode;
import edu.pku.sei.modeler.model.structure.MetaShapeElement;
import edu.pku.sei.modeler.model.uml.Kernel.Operation;
import edu.pku.sei.modeler.model.uml.Kernel.Parameter;
import edu.pku.sei.modeler.model.uml.Kernel.Property;
import edu.pku.sei.modeler.model.uml.Kernel.UMLClass;
import edu.pku.sei.modeler.uml.ResourceFactory;
import edu.pku.sei.modeler.uml.commands.ChangeNameCommand;
import edu.pku.sei.modeler.uml.modelHelper.ModelPackage;

/**
 * @generated
 * 
 */
public class UMLClassEditpart extends AbstractUMLNodeEditPart {
	public UMLClassEditpart(MetaShapeElement model) {
		super(model);
	}

	public void activate() {
		super.activate();
		MetaTypedList attributeList = getModelElement().getOwnedAttribute();
		for (Iterator iter = attributeList.iterator(); iter.hasNext();) {
			Property element = (Property) iter.next();
			element.addPropertyChangeListener(modelListener);

		}

		MetaTypedList operationList = getModelElement().getOwnedOperation();
		for (Iterator iter = operationList.iterator(); iter.hasNext();) {
			Operation operation = (Operation) iter.next();
			operation.addPropertyChangeListener(modelListener);

			for (Iterator iterator = operation.getOwnedParameter().iterator(); iterator
					.hasNext();) {
				Parameter element = (Parameter) iterator.next();
				element.addPropertyChangeListener(modelListener);

			}

		}
	}

	public void deactivate() {
		MetaTypedList attributeList = getModelElement().getOwnedAttribute();
		for (Iterator iter = attributeList.iterator(); iter.hasNext();) {
			Property element = (Property) iter.next();
			element.removePropertyChangeListener(modelListener);

		}

		MetaTypedList operationList = getModelElement().getOwnedOperation();
		for (Iterator iter = operationList.iterator(); iter.hasNext();) {
			Operation element = (Operation) iter.next();
			element.removePropertyChangeListener(modelListener);
		}

		super.deactivate();
	}

	private UMLClass getModelElement() {
		return (UMLClass) ((MetaNode) getModel()).getModelElement();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
	 */
	protected IFigure createFigure() {
		return new UMLClassFigure(new Label());
	}

	protected DirectEditPolicy createDirectEditPolicy() {
		return new DirectEditPolicy() {
			protected Command getDirectEditCommand(DirectEditRequest request) {
				return new ChangeNameCommand(getUMLClass(), (String) request
						.getCellEditor().getValue());
			}

			protected void showCurrentEditValue(DirectEditRequest request) {
				IFigure fig = getDirectEditFigure();
				if (fig instanceof Label) {
					((Label) fig).setText(getUMLClass().getName());
					fig.getUpdateManager().performUpdate();
				}
			}
		};
	}

	@Override
	protected IFigure getDirectEditFigure() {
		return ((UMLClassFigure) this.getFigure()).getNameLabel();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
	 */
	protected void createEditPolicies() {
		super.createEditPolicies();
		// installActionHandle();
	}

	protected void handlePropertyChanged(PropertyChangeEvent event) {
		String property = event.getPropertyName();
		if (ModelPackage.UMLCLASS_ISACTIVE.equals(property)) {
			refreshClassName((UMLClass)getNode().getModelElement(), (UMLClassFigure)getFigure());
		}
		refreshVisuals();
		super.handlePropertyChanged(event);
	}

	private UMLClass getUMLClass() {
		return (UMLClass) ((MetaNode) getModel()).getModelElement();
	}

	@Override
	protected EditPart createChild(Object model) {
		return super.createChild(model);
	}

	protected void refreshVisuals() {
		super.refreshVisuals();

		UMLClass modelElement = (UMLClass) getNode().getModelElement();
		UMLClassFigure classFigure = (UMLClassFigure) getFigure();

		// refresh class name
		refreshClassName(modelElement, classFigure);

		// refresh attributes
		refreshAttributes(modelElement, classFigure);

		// refresh operations
		refreshOperations(modelElement, classFigure);

	}

	// protected void installActionHandle() {
	// ActionHandleManager actionMngr = new ActionHandleManager(this);
	//
	// PaletteDrawer entries = new PaletteDrawer("creation tool");
	// try {
	//
	// AbstractFactory modelFactory =
	// ModelRegistry.getRegistry().getFactory(this.getNode().getModel());
	//
	// StructureFactory sFactory = (StructureFactory)
	// ModelRegistry.getRegistry()
	// .getStructureFactory(this.getNode().getModel());
	//
	// CreationToolEntry propertyToolEntry = new
	// CreationToolEntry(ImageProvider.PROPERTY_IMAGE, "Add New Property", new
	// MetaCreationFactory(true,
	// ModelPackage.__PROPERTY__, modelFactory, sFactory),
	// ImageProvider.getImageDescriptor(ImageProvider.PROPERTY_IMAGE), null);
	//
	// CreationToolEntry operationToolEntry = new
	// CreationToolEntry(ImageProvider.OPERATION_IMAGE, "Add New Operation", new
	// MetaCreationFactory(
	// true, ModelPackage.__OPERATION__, modelFactory, sFactory), ImageProvider
	// .getImageDescriptor(ImageProvider.OPERATION_IMAGE), null);
	//
	// entries.add(propertyToolEntry);
	// entries.add(operationToolEntry);
	// actionMngr.addTool(entries, PositionConstants.SOUTH_EAST);
	//
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// }

	private void refreshOperations(UMLClass modelElement,
			UMLClassFigure classFigure) {
		Figure operationFigure = classFigure.getOpCompart();
		operationFigure.removeAll();

		for (Iterator iter = modelElement.getOwnedOperation().iterator(); iter
				.hasNext();) {
			Label operation = this.getOperationFigure((Operation) iter.next());
			operation.setForegroundColor(ColorConstants.black);
			operationFigure.add(operation);
		}
	}

	private Label getAttributeFigure(final Property utilProperty) {
		Label nameLabelForOneAttribute = new Label();
		String newText = utilProperty.getCustomLabel();
		nameLabelForOneAttribute.setText(newText);
		nameLabelForOneAttribute.setFont(ResourceFactory.getTextFont());
		nameLabelForOneAttribute.setLabelAlignment(PositionConstants.LEFT);
		return nameLabelForOneAttribute;
	}

	public Label getOperationFigure(final Operation utilOperation) {
		Label operationFigure = new Label();
		String newText = utilOperation.getCustomLabel();
		operationFigure.setFont(ResourceFactory.getTextFont());
		operationFigure.setLabelAlignment(PositionConstants.LEFT);
		operationFigure.setText(newText);
		return operationFigure;
	}

	private void refreshClassName(UMLClass modelElement,
			UMLClassFigure classFigure) {
		String className = modelElement.getName();
		Label nameLabel = classFigure.getNameLabel();

		if (modelElement.getIsAbstract()) {
			nameLabel.setFont(ResourceFactory.getHeadItalicsFont());
		} else {
			nameLabel.setFont(ResourceFactory.getHeadFont());
		}

		// nameLabel.setIconAlignment(PositionConstants.TOP);
		nameLabel.setTextAlignment(PositionConstants.CENTER);
		// nameLabel.setIcon(ImageProvider.getImage(ImageProvider.CLASS_IMAGE));
		if (modelElement.getIsActive() == true)
			nameLabel.setText("<<Active>>\n"+className);
		nameLabel.setText(className);

		// nameLabel.setIconTextGap(2);
	}

	protected void refreshAttributes(UMLClass modelElement,
			UMLClassFigure classFigure) {
		// MetaClassFigure fig = (MetaClassFigure)this.getFigure();
		Figure attributeContainer = classFigure.getAttrCompart();
		attributeContainer.removeAll();

		for (Iterator iter = modelElement.getOwnedAttribute().iterator(); iter
				.hasNext();) {
			Label attribute = this.getAttributeFigure((Property) iter.next());
			attribute.setForegroundColor(ColorConstants.black);
			attributeContainer.add(attribute);

		}
	}
}
